import random
from django import forms
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError
from django_redis import get_redis_connection
from django.conf import settings

from web import models
from utils.tencent.tecent_sms import send_sms_single
from utils.encrypt import md5
from web.forms.base_form import BaseForm


class RegisterForm(BaseForm, forms.ModelForm):
    """注册"""
    mobile_phone = forms.CharField(
        label="手机",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        validators=[RegexValidator(r"^1(3|4|5|6|7|8|9)\d{9}$", "手机号格式错误"), ]
    )
    password = forms.CharField(
        label="密码",
        widget=forms.PasswordInput(attrs={"class": "form-control"}),
        min_length=4,
        max_length=12,
        error_messages={
            "min_length": "密码最短为4位",
            "max_length": "密码最长为12位",
        }
    )
    confirm_password = forms.CharField(
        label="确认密码",
        widget=forms.PasswordInput(attrs={"class": "form-control"}),
        min_length=4,
        max_length=12,
        error_messages={
            "min_length": "确认密码最短为4位",
            "max_length": "确认密码最长为12位",
        }
    )
    code = forms.CharField(
        label="验证码",
        widget=forms.TextInput()
    )

    class Meta:
        model = models.UserInfo
        fields = ["username", "password", "confirm_password", "mobile_phone", "code", "email"]

    # def __init__(self, *args, **kwargs):
    #     super().__init__(*args, **kwargs)
    #
    #     for name, field in self.fields.items():
    #         field.widget.attrs['class'] = 'form-control'
    #         field.widget.attrs['placeholder'] = "请输入{}".format(field.label)

    def clean_username(self):
        username = self.cleaned_data.get("username")
        exist = models.UserInfo.objects.filter(username=username).exists()
        if exist:
            raise ValidationError("用户名已存在")
        return username

    def clean_password(self):
        password = self.cleaned_data.get("password")
        # 密码加密，返回
        return md5(password)

    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data.get("mobile_phone")
        exist = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()
        if exist:
            raise ValidationError("手机号已存在")
        return mobile_phone

    def clean_confirm_password(self):
        password = self.cleaned_data.get("password")
        confirm_password = self.cleaned_data.get("confirm_password")

        if password != md5(confirm_password):
            raise ValidationError("两次密码不一致")
        return md5(confirm_password)

    def clean_email(self):
        email = self.cleaned_data.get("email")
        exist = models.UserInfo.objects.filter(email=email).exists()
        if exist:
            raise ValidationError("邮箱已存在")
        return email

    def clean_code(self):
        code = self.cleaned_data.get("code")
        mobile_phone = self.cleaned_data.get("mobile_phone")
        if not mobile_phone:
            return code

        # 从redis中获取验证码
        conn = get_redis_connection()
        redis_code = conn.get(mobile_phone)
        if not redis_code:
            raise ValidationError("验证码已失效")

        str_code = redis_code.decode("utf-8")
        if code.strip() != str_code:
            raise ValidationError("验证码错误")
        return code


class SendSmsForm(forms.Form):
    """发送短信"""
    mobile_phone = forms.CharField(label="手机号", validators=[RegexValidator(r"^1(3|4|5|6|7|8|9)\d{9}$", "手机号格式错误"), ])

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request

    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data['mobile_phone']
        tpl = self.request.GET.get("tpl")
        template_id = settings.TECENT_SMS_TEMPLATE.get(tpl)

        if not template_id:
            raise ValidationError("template模板错误")

        exist = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()
        if tpl == "login":
            if not exist:
                raise ValidationError("手机号不存在")
        else:
            if exist:
                raise ValidationError("手机号已存在")

        # 发送短信
        code = random.randint(1000, 9999)
        # 测试用  #################
        print("code=============", code)
        conn = get_redis_connection()
        conn.set(mobile_phone, code, ex=60)
        # 测试用  #################

        # sms = send_sms_single(phone_num=mobile_phone, template_id=template_id, template_param_list=[code, 2])
        # if sms['result'] == 0:
        #     # 发送成功
        #     print("code=============", code)
        #     conn = get_redis_connection()
        #     conn.set(mobile_phone, code, ex=60)
        # else:
        #     raise ValidationError("短信发送失败，{}".format(sms['errmsg']))

        return mobile_phone


class LoginSmsForm(BaseForm, forms.Form):
    """登录"""
    mobile_phone = forms.CharField(
        label="手机",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        validators=[RegexValidator(r"^1(3|4|5|6|7|8|9)\d{9}$", "手机号格式错误"), ]
    )

    code = forms.CharField(
        label="验证码"
    )

    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data.get("mobile_phone")
        # 根据手机号获取当前用户
        user_obj = models.UserInfo.objects.filter(mobile_phone=mobile_phone).first()
        if not user_obj:
            raise ValidationError("手机号不存在")
        # 返回用户对象，后面的cleaned_data['mobile_phone']就是user_obj了
        return user_obj

    def clean_code(self):
        user_obj = self.cleaned_data["mobile_phone"]
        code = self.cleaned_data['code']
        if not user_obj:
            # 手机号不存在
            return code

        # 从redis中获取验证码，是bytes类型的
        conn = get_redis_connection()
        redis_code = conn.get(user_obj.mobile_phone)
        if not redis_code:
            raise ValidationError("没有验证码")

        str_code = redis_code.decode("utf-8")
        if code.strip() != str_code:
            raise ValidationError("验证码错误")

        return code


class LoginForm(BaseForm, forms.Form):
    """用户名和密码登录"""
    username = forms.CharField(label="邮箱或手机号")
    password = forms.CharField(
        label="密码",
        min_length=4,
        max_length=12,
        error_messages={
            "min_length": "密码最短为4位",
            "max_length": "密码最长为12位",
        },
        widget=forms.PasswordInput(render_value=True)
    )
    code = forms.CharField(label="图片验证码")

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request

    def clean_code(self):
        code = self.cleaned_data["code"]

        session_code = self.request.session.get("image_code")
        if not session_code:
            raise ValidationError("验证码已过期")

        if code.upper() != session_code.upper():
            raise ValidationError("验证码错误")

        return code

    def clean_password(self):
        password = self.cleaned_data["password"]
        return md5(password)
